package puntaelena.facilitylocation.hillclimbing.solver.agents;

import jfuzzyprincepless.negotiation.INegotiationContext;
import puntaelena.facilitylocation.hillclimbing.solver.services.IFcltLocDataService;
import puntaelena.facilitylocation.hillclimbing.solver.services.IHillClimbingAgentRegistry;
import puntaelena.graphsupport.FacilitiesGraph;
import static puntaelena.facilitylocation.hillclimbing.solver.agents.FcltCityNegotiateComputator.*;

public class FacilitySearchsFriendCitiesAgent
	extends BaseFacilityAgent
{
	public FacilitySearchsFriendCitiesAgent(int facility) {
		super(facility);
	}

	@Override
	public boolean negotiate(INegotiationContext context) {
		IHillClimbingAgentRegistry hcagReg =
			context.getService(IHillClimbingAgentRegistry.class);
		IFcltLocDataService flServ =
			context.getService(IFcltLocDataService.class);
		boolean[] isFcltOpen = flServ.getFcltOpen();
		int[] witnesses = flServ.getWitnesses();

		if (isFcltOpen[facility]) {
			return false;
		}

		FacilitiesGraph fgraph = flServ.getFgraph();
		int citiesCount = fgraph.getCitiesCount();

		double sumPayment = 0;
		for (int city = 0; city < citiesCount; city++) {
			CityChoosesFacilityAgent cagent =
				hcagReg.getCityAgent(city);
			double payment = cagent.getReadyToPay(context, this);
			sumPayment += payment;
		}

		assert _ac_profitGTPayment(isFcltOpen, fgraph, witnesses, sumPayment);

		if (sumPayment >= fgraph.getFacilitiesPrices()[facility] - eps) {
			isFcltOpen[facility] = true;
			for (int city = 0; city < citiesCount; city++) {
				CityChoosesFacilityAgent cagent = hcagReg.getCityAgent(city);
				double payment = cagent.getReadyToPay(context, this);
				if (payment > eps) {
					flServ.getWitnesses()[city] = facility;
				}
			}
		}

		return false;
	}

	// assertion checks

	private boolean _ac_profitGTPayment(
		boolean[] isFcltOpen,
		FacilitiesGraph fgraph,
		int[] witnesses,
		double sumPayment
	) {
		isFcltOpen[facility] = true;
		try {
			return computeBestAllWitnessProfit(
				fgraph,
				witnesses,
				isFcltOpen
			) >= sumPayment - eps;
		} finally {
			isFcltOpen[facility] = false;
		}
	}
}